package com.moon.game.server;

import static org.jboss.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST;
import static org.jboss.netty.handler.codec.http.HttpResponseStatus.INTERNAL_SERVER_ERROR;
import static org.jboss.netty.handler.codec.http.HttpResponseStatus.OK;
import static org.jboss.netty.handler.codec.http.HttpVersion.HTTP_1_1;

import java.io.File;
import java.io.FileInputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.DynamicChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import org.jboss.netty.handler.codec.frame.TooLongFrameException;
import org.jboss.netty.handler.codec.http.DefaultHttpResponse;
import org.jboss.netty.handler.codec.http.HttpMethod;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.codec.http.HttpResponse;
import org.jboss.netty.handler.codec.http.HttpResponseStatus;
import org.jboss.netty.handler.codec.http.QueryStringDecoder;
import org.jboss.netty.util.CharsetUtil;

import com.moon.game.constants.Constants;
import com.moon.game.constants.GlobalConstants;
import com.moon.game.message.ObjMessage;
import com.moon.game.proxy.ProxyHandler;
import com.moon.game.proxy.ProxyShow;
import com.moon.game.util.GDateUtils;
import com.moon.game.vos.ErrorMsg;

/**
 * HTTP
 * 
 * @author sky
 * 
 */
public class HttpServerHandler extends SimpleChannelUpstreamHandler {

	private static final Logger log = Logger.getLogger(HttpServerHandler.class);
	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
			throws Exception {
		Channel ch = e.getChannel();
		Throwable cause = e.getCause();
		if (cause instanceof TooLongFrameException) {
			sendError(ctx, BAD_REQUEST);
			return;
		}
		cause.printStackTrace();
		if (ch.isConnected()) {
			sendError(ctx, INTERNAL_SERVER_ERROR);
		}
		ch.close();
	}
	
	private void sendError(ChannelHandlerContext ctx, HttpResponseStatus status) throws Exception {
//		NettyUtil.outErrorMsg(ctx, MessageResource.buildMsg(ErrorCode.ERR_SYS));
		System.out.println("错误信息");
	}

	@Override
	public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
			throws Exception {
		HttpRequest request = (HttpRequest) e.getMessage();
		ObjMessage data = null;
		String uri = request.getUri();
		String pid = null;
		String sid = null;
		if (uri == null) {
			return;
		}
		if (uri.endsWith(".png")||uri.endsWith(".gif")) {
			//图片加载
			HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK);
			// 设置body数据
			ChannelBuffer buffer = new DynamicChannelBuffer(2048);
			FileInputStream fr = new FileInputStream(new File("resources" + uri));
			byte[] image = new byte[fr.available()];
			fr.read(image);
			buffer.writeBytes(image);
			response.setContent(buffer);

			// 设置浏览器header
			response.setHeader("Content-Type", "text/vnd.wap.wml; charset=" + GlobalConstants.UTF_8);
			response.setHeader("Content-Length", response.getContent().writerIndex());
			ctx.getChannel().write(response).addListener(ChannelFutureListener.CLOSE);
			return;
		}
		//直接跳转无app请求的分支
		if (uri.indexOf("/p_C")!=-1 || 
				uri.indexOf("/TA_CD")!=-1 || 
				uri.indexOf("/TA_CTB")!=-1 || 
				uri.indexOf("/TA_RD")!=-1 ||
				uri.indexOf("/TA_RB")!=-1 ||
				uri.indexOf("/TA_PD")!=-1 ||
				uri.indexOf("/TA_ICD")!=-1 ||
				uri.indexOf("/TA_CAD")!=-1 ||
				uri.indexOf("/TA_DD") != -1) {
			if (uri.indexOf("/p_C")!=-1) {
				//p_C创建人物界面。特殊【没有pid】
				data = new ObjMessage();
				data.setCmd(uri.split("[/]")[3]);
				data.setStatus(Constants.STATUS_SUCC);
				data.setVO("sid",uri.split("[/]")[2]);
				ProxyShow.showResult(e.getChannel(), data);
				return;
			}else {
				data = new ObjMessage();
				data.setCmd(ProxyHandler.getCmd(uri));
				data.setStatus(Constants.STATUS_SUCC);
				data.setVO("sid",ProxyHandler.getSid(uri));
				data.setVO("pid", ProxyHandler.getPid(uri));
				ProxyShow.showResult(e.getChannel(), data);
				return;
			}
		}
		if (uri.trim().length() == 1) {
			data = new ObjMessage();
			data.setCmd("LOG_IN");
			data.setStatus(Constants.STATUS_SUCC);
			ProxyShow.showResult(e.getChannel(), data);
			return;
		}
		if (uri.equals("/LOG_IN")) {
			//获取POST传上来的数据
			HttpMethod method = request.getMethod();
			if (!"POST".equals(method.getName())) {
				data = new ObjMessage();
				data.setCmd("LOG_IN");
				data.setStatus(Constants.STATUS_SUCC);
				ProxyShow.showResult(e.getChannel(), data);
				return;
			}
			Map<String, List<String>> ps = getParameters(request, ctx);
			if (ps == null) {
				ProxyShow.outResponseStatu(ctx.getChannel(), HttpResponseStatus.OK);
				return;
			}
			sid = ps.get("qq").get(0);
			String password = ps.get("password").get(0);
			data = new ObjMessage();
			data.setCmd("LOG_IN");
			data.setStatus(Constants.STATUS_SUCC);
			data.setSid(sid);
			data.setIp(e.getRemoteAddress().toString());
			data.setVO("password", password);
		}else if (uri.indexOf("/P_CP")!=-1) {
			//创建人物
			//获取POST传上来的数据
			HttpMethod method = request.getMethod();
			if (!"POST".equals(method.getName())) {
				data = new ObjMessage();
				data.setCmd("LOG_IN");
				data.setStatus(Constants.STATUS_SUCC);
				ProxyShow.showResult(e.getChannel(), data);
				return;
			}
			Map<String, List<String>> ps = getParameters(request, ctx);
			if (ps == null) {
				ProxyShow.outResponseStatu(ctx.getChannel(), HttpResponseStatus.OK);
				return;
			}
			String name = ps.get("name").get(0);
			String sex = ps.get("sex").get(0);
			data = new ObjMessage();
			data.setCmd("P_CP");
			data.setStatus(Constants.STATUS_SUCC);
			data.setIp(e.getRemoteAddress().toString());
			data.setVO("name", name);
			data.setVO("sex", sex);
			data.setSid(uri.split("[/]")[1]);
		}else {
			if (uri.indexOf("favicon.ico") != -1 || uri.startsWith("img") || uri.startsWith("sc")) {// 忽略请求
				ProxyShow.outResponseStatu(ctx.getChannel(), HttpResponseStatus.OK);
				return;
			}
			//TODO:以后打开书签验证
			/*if (!ProxyHandler.checkTime(uri)) {
				//书签过期验证未通过
				log.debug("make is out time...");
				//TODO:输出过期书签,或者跳转到登录页面
				return;
			}*/
			String cmd = ProxyHandler.getCmd(uri);
			if ("".equals(cmd)) {
				//cmd异常
				data = new ObjMessage();
				data.setCmd("E_CMD");
				data.setStatus(Constants.STATUS_FAIL);
				data.setVO("sid",ProxyHandler.getSid(uri));
				data.setVO("pid", ProxyHandler.getPid(uri));
				ProxyShow.showResult(e.getChannel(), data);
				return;
			}
			sid = ProxyHandler.getSid(uri);
			if ("".equals(sid)) {
				//sid异常
				data = new ObjMessage();
				data.setCmd("E_SID");
				data.setStatus(Constants.STATUS_FAIL);
				data.setVO("sid",ProxyHandler.getSid(uri));
				data.setVO("pid", ProxyHandler.getPid(uri));
				ProxyShow.showResult(e.getChannel(), data);
				return;
			}
			pid = ProxyHandler.getPid(uri);
			if ("".equals(pid)) {
				//pid异常
				data = new ObjMessage();
				data.setCmd("E_PID");
				data.setStatus(Constants.STATUS_FAIL);
				data.setVO("sid",ProxyHandler.getSid(uri));
				data.setVO("pid", ProxyHandler.getPid(uri));
				ProxyShow.showResult(e.getChannel(), data);
				return;
			}
			data = new ObjMessage();
			data.setIp(e.getRemoteAddress().toString());
			data.setStartTime(GDateUtils.now());
			data.setVO("uri", uri);
			
			
			//几个特殊的cmd，需要出传入post内容
			if ("C_SM".equals(cmd)) {
				//发送消息
				ChannelBuffer cb = request.getContent();
				if (!cb.readable()) {
					ProxyShow.outResponseStatu(ctx.getChannel(), HttpResponseStatus.OK);
					return;
				}
				String param = cb.toString(CharsetUtil.UTF_8);
				QueryStringDecoder queryStringDecoder = new QueryStringDecoder("/?" + param);
				Map<String, List<String>> ps = queryStringDecoder.getParameters();
				String content = ps.get("content").get(0);
				if (content.length() > 30) {
					ObjMessage result = new ObjMessage("fail");
					result.setCmd("E_INFO");
					HashMap<String, Object> err_data = new HashMap<String, Object>();
					err_data.put("pid", pid);
					result.setData(err_data);
					result.setVO("err_msg",  ErrorMsg.build(-1,"消息长度限制在30个字以内！<br/>"));
					ProxyShow.showError(e.getChannel(), result);
					return;
				}
				String[] tempPs = ProxyHandler.getPs(uri);
				if (tempPs == null) {
					ObjMessage result = new ObjMessage("fail");
					result.setCmd("E_PS");
					ProxyShow.showError(e.getChannel(), result);
					return;
				}
				String[] lastPs = new String[tempPs.length + 1];
				if (tempPs.length >= 2) {
					for (int i = 0; i < tempPs.length; i++) {
						if (i == 0) {
							lastPs[i] = tempPs[i];
							continue;
						} else if (i == 1) {
							lastPs[i] = content;
							lastPs[i + 1] = tempPs[1];
						} else {
							lastPs[i + 1] = tempPs[i];
						}
					}
				} else {
					lastPs[0] = tempPs[0];
					lastPs[1] = content;
				}
				data.setPs(lastPs);
			}else if ("B_UAI".equals(cmd)) {
				//使用加成道具
				Map<String, List<String>> ps = getParameters(request, ctx);
				if (ps == null) {
					ProxyShow.outResponseStatu(ctx.getChannel(), HttpResponseStatus.OK);
					return;
				}
				int num = 1;
				Integer content = Integer.parseInt(ps.get("num").get(0));
				if (content != null) {
					num = content.intValue();
				}
				String[] tempPs = ProxyHandler.getPs(uri);
				if (tempPs == null) {
					ObjMessage result = new ObjMessage("fail");
					result.setCmd("E_PS");
					ProxyShow.showError(e.getChannel(), result);
					return;
				}
				String[] lastPs = new String[tempPs.length + 1];
				if (tempPs.length >= 2) {
					for (int i = 0; i < tempPs.length; i++) {
						if (i == 0) {
							lastPs[i] = tempPs[i];
							continue;
						} else if (i == 1) {
							lastPs[i] = String.valueOf(num);
							lastPs[i + 1] = tempPs[1];
						} else {
							lastPs[i + 1] = tempPs[i];
						}
					}
				} else {
					lastPs[0] = tempPs[0];
					lastPs[1] = String.valueOf(content);
				}
				data.setPs(lastPs);
			}else if ("TR_SI".equals(cmd)) {
				//出售道具
				ChannelBuffer cb = request.getContent();
				String param = cb.toString(CharsetUtil.UTF_8);
				QueryStringDecoder queryStringDecoder = new QueryStringDecoder("/?" + param);
				Map<String, List<String>> ps = queryStringDecoder.getParameters();
				if (ps != null && ps.size() > 0) {
					int num = 1;
					Integer content = Integer.parseInt(ps.get("num").get(0));
					if (content != null) {
						num = content.intValue();
					}
					String[] tempPs = ProxyHandler.getPs(uri);
					if (tempPs == null) {
						ObjMessage result = new ObjMessage("fail");
						result.setCmd("E_PS");
						ProxyShow.showError(e.getChannel(), result);
						return;
					}
					String[] lastPs = new String[tempPs.length + 1];
					if (tempPs.length > 0) {
						for (int i = 0; i < tempPs.length; i++) {
							lastPs[i] = tempPs[i];
						}
						lastPs[tempPs.length] = String.valueOf(num);
					}
					data.setPs(lastPs);
				}else {
					data.setPs(ProxyHandler.getPs(uri));
				}
				
			}else if ("TR_BI".equals(cmd)) {
				//购买道具
				ChannelBuffer cb = request.getContent();
				String[] clientPs = ProxyHandler.getPs(uri);
				if (clientPs == null) {
					ObjMessage result = new ObjMessage("fail");
					result.setCmd("E_PS");
					ProxyShow.showError(e.getChannel(), result);
					return;
				}else if (clientPs.length == 1) {
					int buyNum = 1;
					//等待确认的购买道具
					if (cb.readable()) {
						String param = cb.toString(CharsetUtil.UTF_8);
						QueryStringDecoder queryStringDecoder = new QueryStringDecoder("/?" + param);
						Map<String, List<String>> ps = queryStringDecoder.getParameters();
						Integer content = Integer.parseInt(ps.get("num").get(0));
						if (ps != null && ps.size() > 0 && content != null) {
							buyNum = content.intValue();
						}
					}
					String[] lastPs = new String[clientPs.length + 1];
					if (clientPs.length > 0) {
						for (int i = 0; i < clientPs.length; i++) {
							lastPs[i] = clientPs[i];
						}
						lastPs[clientPs.length] = String.valueOf(buyNum);
					}
					data.setPs(lastPs);
				}else {
					data.setPs(ProxyHandler.getPs(uri));
				}
			}else if ("TA_RTL".equals(cmd)) {
				//购买道具
				ChannelBuffer cb = request.getContent();
				String[] clientPs = ProxyHandler.getPs(uri);
				if (clientPs == null) {
					ObjMessage result = new ObjMessage("fail");
					result.setCmd("E_PS");
					ProxyShow.showError(e.getChannel(), result);
					return;
				}else if (clientPs.length == 1) {
					int price = 1;
					//等待确认的购买道具
					String[] lastPs = ProxyHandler.getPs(uri);
					if (cb.readable()) {
						String param = cb.toString(CharsetUtil.UTF_8);
						QueryStringDecoder queryStringDecoder = new QueryStringDecoder("/?" + param);
						Map<String, List<String>> ps = queryStringDecoder.getParameters();
						Integer content = Integer.parseInt(ps.get("num").get(0));
						if (ps != null && ps.size() > 0 && content != null) {
							price = content.intValue();
						}
						lastPs = new String[clientPs.length + 1];
						if (clientPs.length > 0) {
							for (int i = 0; i < clientPs.length; i++) {
								lastPs[i] = clientPs[i];
							}
							lastPs[clientPs.length] = String.valueOf(price);
						}
					}
					data.setPs(lastPs);
				}else {
					data.setPs(ProxyHandler.getPs(uri));
				}
			}else {
				//普通情况
				data.setPs(ProxyHandler.getPs(uri));
			}
			data.setPid(pid);
			data.setSid(sid);
			data.setCmd(cmd);
		}
		Channel channel = e.getChannel();
		NetServer.handleRequest(channel, data);
		long startTime = System.currentTimeMillis();
		synchronized (channel) {
			channel.wait(3000);
		}
		long endTime = System.currentTimeMillis();
		ObjMessage result = NetServer.getResponseMsg(data.getSid());
		log.debug("[" + pid + "]used " + (endTime - startTime) + "to operate " + data.getCmd());
		if(result==null){
			log.error("result is null,request uri:[" + uri + "]");
			result = new ObjMessage("fail");
			HashMap<String, Object> errData = new HashMap<String, Object>();
			errData.put("pid", pid);
			errData.put("sid", sid);
			result.setData(errData);
			result.setCmd("E_INFO");
			result.setVO("err_msg",  ErrorMsg.build(-1,"系统忙，请稍后再试..."));
    	} else if(data.getPid() != null && !data.getPid().equals(result.getPid())){
			log.error("[recv:pid="+data.getPid()+",info:" + result.toString() + "]");
			log.error("diffent player error:"+result.getPid()+"-"+data.getPid());
			result = new ObjMessage("fail");
			HashMap<String, Object> errData = new HashMap<String, Object>();
			errData.put("pid", pid);
			errData.put("sid", sid);
			result.setData(errData);
			result.setCmd("E_INFO");
			result.setVO("err_msg",  ErrorMsg.build(-1,"系统出现问题,请刷新继续..."));
		}else{
			log.info("[recv:pid="+data.getPid()+",info:" + result.toString() + "]");
		}
		if ("fail".equals(result.getStatus())) {
			ProxyShow.showError(channel, result);
			return;
		}
		ProxyShow.showResult(channel, result);
	}
	
	
	
	/**
	 * 获取post参数信息
	 * 
	 * @param request
	 * @param ctx
	 */
	private Map<String, List<String>> getParameters(HttpRequest request, ChannelHandlerContext ctx) {
		ChannelBuffer cb = request.getContent();
		if (!cb.readable()) {
			return null;
		}
		String param = cb.toString(CharsetUtil.UTF_8);
		QueryStringDecoder queryStringDecoder = new QueryStringDecoder("/?" + param);
		Map<String, List<String>> ps = queryStringDecoder.getParameters();
		return ps;
	}
}
